package com.qzsoft.zhjd.server.modules.glodon.gys.wl.service.impl;

import cn.hutool.core.convert.NumberChineseFormater;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.glodon.cloudt.rest.client.exception.InvalidUriException;
import com.glodon.cloudt.rest.client.exception.NoAuthenticateException;
import com.glodon.gys.rest.client.impl.GysRestClientNew;
import com.qzsoft.jeemis.common.utils.Result;
import com.qzsoft.zhjd.server.modules.glodon.gys.wl.domain.dto.PageBillsInfo;
import com.qzsoft.zhjd.server.modules.glodon.gys.wl.domain.dto.WeighbridgeBills;
import com.qzsoft.zhjd.server.modules.glodon.gys.wl.domain.entity.WeighbridgeData;
import com.qzsoft.zhjd.server.modules.glodon.gys.wl.mapper.WeighbridgeDataMapper;
import com.qzsoft.zhjd.server.modules.glodon.gys.wl.service.IGysWlJdPlatformService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 济德 广联达 平台 对接
 */
@Slf4j
@Service
public class GysWlJdPlatformServiceImpl implements IGysWlJdPlatformService {

    /**
     * 站点ID值，
     * <p>
     * 应该是动态的赋值！
     */
    @Deprecated
    private String stationId = "JD-01";

    @Autowired
    @Qualifier("gysRestClient_jd")
    private GysRestClientNew gysRestClient_ws;

    @Autowired
    private WeighbridgeDataMapper weighbridgeDataMapper;

    /**
     * 获取正常收料磅单
     *
     * @param projectId      项目ID，可为空；若使用租户层授权文件时，projectId为空查询全部项目数据，不为空时只查询对应项目的数据；若使用项目层授权文件时，为空则查询授权文件所属项目及下属拌合站的数据；不为空时只查询对应项目的数据；
     * @param beginTimestamp 开始时间, 字符串,时间包含毫秒，格式为yyyyMMddHHmmssSSS, 不能为空，如 20160319101010000，2016年3月19号10点10分10秒000毫秒
     * @param hasPicture     需要携带榜单图片。true：包含磅单图片，false：不包含磅单图片
     * @return
     * @see <a href="https://xmgl.glodon.com/wl/docs/third_help/part2/openapi/pull/billTotal.html#%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E">获取磅单接口</a>
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result getSLlist(String projectId, String beginTimestamp, Boolean hasPicture) {

        Result result = new Result();

        String url = "/gys/inspection-api-service/integrate-v2/getSLlist";

        if (StringUtils.isEmpty(beginTimestamp)) {
            log.warn("[GYS] - WL >>> 获取正常收料磅单失败：{}！", "起始时间有误");
            return result.error(500, "起始时间有误");
        }
        url += "?beginTimestamp=" + beginTimestamp;
        if (Boolean.TRUE.equals(hasPicture)) {
            url += "&hasPicture=true";
        }
        if (!StringUtils.isEmpty(projectId)) {
            url += "&projectId=" + projectId;
        }

        // 获取值！
        com.glodon.gys.rest.client.data.Result<JSONObject> gysResult = null;
        try {
            gysResult = gysRestClient_ws.get(url);
        } catch (InvalidUriException e) {
            // throw new RuntimeException(e);
            log.error("无效的URI");
        } catch (NoAuthenticateException e) {
            // throw new RuntimeException(e);
            log.error("鉴权验证失败");
        }

        if (!gysResult.isSuccess()) {
            log.warn("[GYS] - WL >>> 获取正常收料磅单失败：{}！", gysResult.getErrorMessage());
            return result.error(500, gysResult.getErrorMessage());
        }
        // 转一下，方便使用！
        PageBillsInfo<WeighbridgeBills> billsPageInfo = JSON.parseObject(JSONObject.toJSONString(gysResult.getData()), new TypeReference<PageBillsInfo<WeighbridgeBills>>() {
        });

        List<WeighbridgeBills> infoBills = billsPageInfo.getBills();
        if (infoBills == null || infoBills.isEmpty()) {
            log.warn("[GYS] - WL >>> 获取正常收料磅单数据为空！");
            return result.ok(billsPageInfo);
        }

        List<WeighbridgeBills> supplement = new ArrayList<>(infoBills.size()); // 预先申请容量！

        // 1、获取本地已经存储的数据
        String endTimestamp = "";
        DateTime parsed = DateUtil.parse(beginTimestamp);
        List<String> uniqueGuidCodes = weighbridgeDataMapper.getAllUniqueCodeByTimeRange(parsed.toString(), endTimestamp, stationId);

        // 2、执行 远程与本地去重
        if (uniqueGuidCodes.isEmpty()) {
            // 直接全部存入即可！
            supplement.addAll(infoBills);
        } else {
            // 剔除已经存在的
            List<WeighbridgeBills> _supplement = infoBills.stream()
                .filter(e -> !uniqueGuidCodes.contains(e.getGUID()))
                .collect(Collectors.toList());
            supplement.addAll(_supplement);
        }

        // 3、数据映射拷贝
        List<WeighbridgeData> weighbridgeDataList = dataMapping(supplement, stationId);

        // 4、数据入库本地
        int rows = weighbridgeDataMapper.batchInsert(weighbridgeDataList);


        // 5、汇总打印一下
        log.info("[GYS] - WL >>> 获取正常收料磅单数据：", weighbridgeDataList.size());

        return result.ok(billsPageInfo);
    }


    /**
     * 获取正常发料磅单
     *
     * @param projectId      项目ID，可为空；若使用租户层授权文件时，projectId为空查询全部项目数据，不为空时只查询对应项目的数据；若使用项目层授权文件时，为空则查询授权文件所属项目及下属拌合站的数据；不为空时只查询对应项目的数据；
     * @param beginTimestamp 开始时间, 字符串,时间包含毫秒，格式为yyyyMMddHHmmssSSS, 不能为空，如 20160319101010000，2016年3月19号10点10分10秒000毫秒
     * @param hasPicture     需要携带榜单图片。true：包含磅单图片，false：不包含磅单图片
     * @see <a href="https://xmgl.glodon.com/wl/docs/third_help/part2/openapi/pull/billTotal.html#%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E">获取磅单接口</a>
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result getFLlist(String projectId, String beginTimestamp, Boolean hasPicture) {
        Result result = new Result();

        String url = "/gys/inspection-api-service/integrate-v2/getFLlist";

        if (StringUtils.isEmpty(beginTimestamp)) {
            log.warn("[GYS] - WL >>> 获取正常发料磅单失败：{}！", "起始时间有误");
            return result.error(500, "起始时间有误");
        }
        url += "?beginTimestamp=" + beginTimestamp;
        if (Boolean.TRUE.equals(hasPicture)) {
            url += "&hasPicture=true";
        }
        if (!StringUtils.isEmpty(projectId)) {
            url += "&projectId=" + projectId;
        }

        // 获取值！
        com.glodon.gys.rest.client.data.Result<JSONObject> gysResult = null;
        try {
            gysResult = gysRestClient_ws.get(url);
        } catch (InvalidUriException e) {
            // throw new RuntimeException(e);
            log.error("无效的URI");
        } catch (NoAuthenticateException e) {
            // throw new RuntimeException(e);
            log.error("鉴权验证失败");
        }

        if (!gysResult.isSuccess()) {
            log.warn("[GYS] - WL >>> 获取正常发料磅单失败：{}！", gysResult.getErrorMessage());
            return result.error(500, gysResult.getErrorMessage());
        }
        // 转一下，方便使用！
        PageBillsInfo<WeighbridgeBills> billsPageInfo = JSON.parseObject(JSONObject.toJSONString(gysResult.getData()), new TypeReference<PageBillsInfo<WeighbridgeBills>>() {
        });

        List<WeighbridgeBills> infoBills = billsPageInfo.getBills();
        if (infoBills == null || infoBills.isEmpty()) {
            log.warn("[GYS] - WL >>> 获取正常发料磅单数据为空！");
            return result.ok(billsPageInfo);
        }

        List<WeighbridgeBills> supplement = new ArrayList<>(infoBills.size()); // 预先申请容量！

        // 1、获取本地已经存储的数据
        String endTimestamp = DatePattern.PURE_DATETIME_MS_FORMAT.format(new Date());
        DateTime parsed = DateUtil.parse(beginTimestamp);
        List<String> uniqueGuidCodes = weighbridgeDataMapper.getAllUniqueCodeByTimeRange(parsed.toString(), endTimestamp, stationId);

        // 2、执行 远程与本地去重
        if (uniqueGuidCodes.isEmpty()) {
            // 直接全部存入即可！
            supplement.addAll(infoBills);
        } else {
            // 剔除已经存在的
            List<WeighbridgeBills> _supplement = infoBills.stream()
                .filter(e -> !uniqueGuidCodes.contains(e.getGUID()))
                .collect(Collectors.toList());
            supplement.addAll(_supplement);
        }

        // 3、数据映射拷贝
        List<WeighbridgeData> weighbridgeDataList = dataMapping(supplement, stationId);

        // 4、数据入库本地
        int rows = weighbridgeDataMapper.batchInsert(weighbridgeDataList);

        // 5、汇总打印一下
        log.info("[GYS] - WL >>> 获取正常发料磅单数据：", weighbridgeDataList.size());

        return result.ok(billsPageInfo);
    }

    /**
     * 数据映射一下！
     */
    private List<WeighbridgeData> dataMapping(List<WeighbridgeBills> supplement, String stationId) {

        List<WeighbridgeData> weighbridgeDataList = new ArrayList<>(supplement.size());

        supplement.forEach(weighbridgeBillItem -> {

            // 磅单材料详情 列表
            List<WeighbridgeBills.BillMaterial> bdcl = weighbridgeBillItem.getBDCL();

            DateTime parsed = DateUtil.parse(weighbridgeBillItem.getCPSJ(), DatePattern.PURE_DATETIME_FORMAT); // 创建时间


            WeighbridgeData weighbridgeData = new WeighbridgeData();

            weighbridgeData.setLiushuihao(weighbridgeBillItem.getBDBH());
            weighbridgeData.setChehao(weighbridgeBillItem.getCPH());
            weighbridgeData.setZhenghao(weighbridgeBillItem.getCPH()); // zhenghao	证号

            String _pinming = bdcl.stream().map(WeighbridgeBills.BillMaterial::getCLMC).collect(Collectors.joining("、"));
            weighbridgeData.setPinming(_pinming);
            weighbridgeData.setDanwei(weighbridgeBillItem.getGYSMC());
            weighbridgeData.setMaozhong(BigDecimal.valueOf(weighbridgeBillItem.getMZ()));
            weighbridgeData.setPizhong(BigDecimal.valueOf(weighbridgeBillItem.getPZ()));
            weighbridgeData.setJingzhong(BigDecimal.valueOf(weighbridgeBillItem.getJZ()));

            weighbridgeData.setMaozhongsibang(weighbridgeBillItem.getJBRJC());
            weighbridgeData.setPizhongsibang(weighbridgeBillItem.getJBRCC());
            weighbridgeData.setMaozhongshijian(DateUtil.parse(weighbridgeBillItem.getCMSJ(), DatePattern.PURE_DATETIME_FORMAT));
            weighbridgeData.setPizhongshijian(DateUtil.parse(weighbridgeBillItem.getCPSJ(), DatePattern.PURE_DATETIME_FORMAT));

            weighbridgeData.setRiqi(parsed);

            // zhefangxishu	折方系数
            weighbridgeData.setZhefangxishu("0");
            // fangliang	方量
            weighbridgeData.setFangliang(BigDecimal.ZERO);
            // feiyong	费用
            weighbridgeData.setFeiyong(BigDecimal.ZERO);
            weighbridgeData.setJinedaxie("零"); // jinedaxie	金额大写

            weighbridgeData.setWancheng(String.valueOf(weighbridgeBillItem.getSTATUS()));

            weighbridgeData.setZhongliang(String.valueOf(weighbridgeBillItem.getJZ()));

            // lingkoupinming	零口品名
            // shijikouliang	实际口量

            // lingkou	零口
            // lingkou2	零口2

            if ("吨".equals(weighbridgeBillItem.getGBDW())) { // shizhong	实重
                // 吨单位换算为千克！
                BigDecimal multiply = BigDecimal.valueOf(weighbridgeBillItem.getJZ()).multiply(new BigDecimal(1000));
                weighbridgeData.setShizhong(multiply);
            } else {
                weighbridgeData.setShizhong(BigDecimal.valueOf(weighbridgeBillItem.getJZ()));
            }
            weighbridgeData.setDaxie(NumberChineseFormater.format(weighbridgeBillItem.getJZ(), true, false) + weighbridgeBillItem.getGBDW()); // 大写

            weighbridgeData.setDanjia(BigDecimal.ZERO);

            weighbridgeData.setBei1("文双2-01"); // bei1	备注1
            weighbridgeData.setFeiyong2(BigDecimal.ZERO);  // feiyong2	费用2
            weighbridgeData.setBei2(weighbridgeBillItem.getLX_YT());  // bei2	备注2
            String _guige = bdcl.stream().map(WeighbridgeBills.BillMaterial::getGGXH).collect(Collectors.joining("、"));
            weighbridgeData.setGuige(_guige); // guige	规格型号

            if (weighbridgeBillItem.getSTATUS() == 1) { // zhuangtai 状态
                weighbridgeData.setZhuangtai("正常");
            } else if (weighbridgeBillItem.getSTATUS() == 0) {
                weighbridgeData.setZhuangtai("作废");
                weighbridgeData.setZuofeishijian(DateUtil.parse(weighbridgeBillItem.getLASTUPDATETIME())); // 作废时间(不确定值)
            }

            weighbridgeData.setFahuoyuan(weighbridgeBillItem.getGBY()); // fahuoyuan	发货员

            // fuyongshijian	复用时间

            weighbridgeData.setXiugaishijian(DateUtil.parse(weighbridgeBillItem.getLASTUPDATETIME())); // xiugaishijian	修改时间

            weighbridgeData.setErpdouble(BigDecimal.ZERO); // erpdouble	ERP双
            weighbridgeData.setLeijicheci(0); // leijicheci	累计车次
            weighbridgeData.setLeijizhong(BigDecimal.ZERO); // leijizhong	累计重
            weighbridgeData.setLeijijine(BigDecimal.ZERO); // leijijine	累计金额
            weighbridgeData.setYuanfa(BigDecimal.ZERO); // yuanfa	原发
            weighbridgeData.setSunhao(BigDecimal.ZERO); // sunhao	损耗
            weighbridgeData.setYucunliushui("0"); // yucunliushui	预存流水

            weighbridgeData.setBei3(weighbridgeBillItem.getHTMC()); // bei3	备注3

            // bei4	备注4
            // bei5	备注5

            weighbridgeData.setPizhongyichang(String.valueOf(weighbridgeBillItem.getPZPCJG())); // pizhongyichang	皮重异常
            if (weighbridgeBillItem.getPCJG() == 0) { // yichangxinxi	异常信息
                weighbridgeData.setYichangxinxi("正常");
            } else if (weighbridgeBillItem.getPCJG() == 1) {
                weighbridgeData.setYichangxinxi("超正差");
            } else if (weighbridgeBillItem.getPCJG() == -1) {
                weighbridgeData.setYichangxinxi("超负差");
            }

            // diqu	地区
            // quhao 区号

            weighbridgeData.setGongsi(weighbridgeBillItem.getGYSMC()); // gongsi	公司
            weighbridgeData.setZidingliushui(weighbridgeBillItem.getBDBH()); // zidingliushui	自定义流水

            if (weighbridgeBillItem.getLX() == 0) { // leixing	类型
                weighbridgeData.setLeixing("收料");
            } else if (weighbridgeBillItem.getLX() == 1) {
                weighbridgeData.setLeixing("发料");
            }

            weighbridgeData.setBei6("文双2分部地磅01#"); // bei6	备注6
            weighbridgeData.setBei7(weighbridgeBillItem.getKFMC()); // bei7	备注7

            weighbridgeData.setShangchuan("YES"); // shangchuan	上传

            // jiesuan	结算
            // jiesuanriqi	结算日期
            // jiesuanbeizhu	结算备注

            weighbridgeData.setShangchuanshijian(parsed); // shangchuanshijian	上传时间
            weighbridgeData.setJinxiaoliushui(weighbridgeBillItem.getBDBH()); // jinxiaoliushui	进出流水
            weighbridgeData.setShuifenkouzhong(BigDecimal.ZERO);   // shuifenkouzhong	水分扣重
            weighbridgeData.setYunfeidanjia(BigDecimal.ZERO);    // yunfeidanjia	运费单价
            weighbridgeData.setYingjieyunfei(BigDecimal.ZERO);  // yingjieyunfei	应结运费
            weighbridgeData.setYunfeijine(BigDecimal.ZERO);  // yunfeijine	运费金额
            weighbridgeData.setKouyunfei(BigDecimal.ZERO);  // kouyunfei	扣运费
            weighbridgeData.setKouhuokuan(BigDecimal.ZERO);  // kouhuokuan	扣货款
            weighbridgeData.setYunfeidaxie("零");  // yunfeidaxie	运费大写
            weighbridgeData.setShijiliushui(parsed.toDateStr());  // shijiliushui	实际流水

            // fujian1	附件1
            // fujian2	附件2
            // fujian3	附件3
            // fujian4	附件4
            // fujian5	附件5
            // fujian6	附件6
            // fajian1	发件1
            // fajian2	发件2
            // fajian3	发件3
            // fajian4	发件4
            // beiyongjine	备用金额
            // tebieshu1	特殊数1
            // tebieshu2	特殊数2
            // tebiewenzi	特殊文字
            // baoguanyijian	保管意见

            weighbridgeData.setBianhao(weighbridgeBillItem.getBDBH()); // bianhao	编号(关联达用作流水号记录)(唯一)
            // fuhe	复核
            // cangguan	仓管
            // yifuhe	已复核
            // liuliang	流量
            // liusunhao	流损耗
            // beiyong1	备用1
            // beiyong2	备用2
            // zhuangxiefei	装卸费
            // guoqiaofei	过桥费
            // jiayoufei	加油费
            // xiuchefei	修车费
            // qitafei	其他费
            weighbridgeData.setTiaoma(weighbridgeBillItem.getBDBH()); // tiaoma	条码
            // kahao	卡号
            // jiesuanliushui	结算流水
            // piciliushui	批次流水
            // danjia2	单价2
            // jine2	金额2
            // danjia3	单价3
            // jine3	金额3
            // kou3	扣3
            // kou4	扣4
            // ankou	暗扣
            // jiesuan1	结算1
            // jiesuan2	结算2
            // weijiesuan	未结算
            // pingmingID	品名ID
            // danweiID	单位ID
            // guigeID	规格ID
            // bei1ID	备注1ID
            // bei2ID	备注2ID
            // bei3ID	备注3ID
            // bei4ID	备注4ID
            // bei5ID	备注5ID
            // bei6ID	备注6ID
            // bei7ID	备注7ID
            // gongchengID	工程ID
            // laiyuanID	来源ID
            weighbridgeData.setXiangmuID(String.valueOf(weighbridgeBillItem.getProjectId())); // xiangmuID	项目ID
            weighbridgeData.setFasongzhuangtai("已同步"); // fasongzhuangtai	发送状态
            weighbridgeData.setCuowuxinxi("无");  // cuowuxinxi	错误信息
            weighbridgeData.setZhandianID(String.valueOf(weighbridgeBillItem.getProjectId())); // zhandianID	站点ID
            weighbridgeData.setZhandianming(weighbridgeBillItem.getProjectName()); // zhandianming	站点名
            weighbridgeData.setDibanghao("01");  // dibanghao	地磅号
            // shengchanshebeiID	生产设备ID
            // shengchanshebeiname	生产设备名
            // zuizhongshuliang	最终数量
            // beiyongshuzi	备用数字
            // yajin	押金
            // yituiyajin	已退押金
            // yajinbiaoji	押金标记
            // yajinbeizhu	押金备注
            // tuiyajintime	退押金时间
            weighbridgeData.setStationId(stationId); // stationId	场站ID（即type）
            weighbridgeData.setIndexId(weighbridgeBillItem.getId()); // indexId	源数据ID
            // send	是否发送给第三方，1，已发送；0未发送。
            weighbridgeData.setSend(1);
            weighbridgeData.setGuid(weighbridgeBillItem.getGUID());

            weighbridgeDataList.add(weighbridgeData);
        });
        return weighbridgeDataList;
    }
}
